package com.cm.etax;

import cn.hutool.core.lang.ClassScanner;
import com.cm.etax.exceptions.EtaxException;
import com.cm.rpa.RpaCore;
import com.cm.rpa.config.RpaConfig;

import java.lang.reflect.Modifier;
import java.util.LinkedHashMap;
import java.util.Objects;

/**
 * 电子税务局业务对象基础类
 *
 * @author LWang 2023.01.29
 * @since 1.0.0
 */
public abstract class BaseEtax {

    private final EtaxConfig config;

    private final RpaCore rpa;

    private final LinkedHashMap<Class<? extends BaseFunction>, BaseFunction> functions;

    protected static final String[] ROLES_TAX = {"法人", "法定代表人", "财务负责人", "办税员"};

    protected static final String[] ROLES_INVOICE = {"法人", "法定代表人", "财务负责人", "开票员"};

    /**
     * 停用服务
     */
    public void shutdown() {
        if (Objects.isNull(rpa)) {
            return;
        }
        rpa.stop();
    }

    /**
     * 构造电子税务局业务对象
     *
     * @param config         RPA 配置
     * @param etaxConfigFile 电子税务局配置
     */
    protected BaseEtax(RpaConfig config, String etaxConfigFile) {
        this.config = EtaxConfig.build(etaxConfigFile);
        this.rpa = new RpaCore(config);
        this.functions = loadFunctions(this.getClass().getPackage());
    }

    /**
     * 在指定包下，扫描 BaseFunction 的子类，并进行初始化
     *
     * @param pg 要扫描的包
     * @return 扫描结果
     */
    public LinkedHashMap<Class<? extends BaseFunction>, BaseFunction> loadFunctions(Package pg) {
        final var result = new LinkedHashMap<Class<? extends BaseFunction>, BaseFunction>();
        ClassScanner.scanPackage(pg.getName(), BaseFunction.class::isAssignableFrom).forEach(c -> {
            try {
                if (!Modifier.isAbstract(c.getModifiers())) {
                    result.put(
                            (Class<BaseFunction>) c,
                            (BaseFunction) c.getConstructor(BaseEtax.class).newInstance(this)
                    );
                }
            } catch (ReflectiveOperationException e) {
                throw new RuntimeException(e);
            }
        });
        return result;
    }

    protected EtaxConfig config() {
        return this.config;
    }

    public RpaCore rpa() {
        return this.rpa;
    }

    protected LinkedHashMap<Class<? extends BaseFunction>, BaseFunction> functions() {
        return this.functions;
    }

    public <T extends BaseFunction> T function(Class<T> functionClass) {
        var function = this.functions.get(functionClass);
        if (functionClass.isInstance(function)) {
            return (T) this.functions.get(functionClass);
        } else {
            throw new EtaxException(functionClass.getName() + " 方法对象不存在！");
        }
    }

    private String[] roles = ROLES_TAX;

    /**
     * 角色类型：办税角色
     */
    public final static int ROLE_TYPE_TAX = 0;

    /**
     * 角色类型：发票角色
     */
    public final static int ROLE_TYPE_INVOICE = 1;

    /**
     * 设置角色
     *
     * @param roleType 角色类型：0：办税；1：发票
     */
    protected void setRole(int roleType) {
        this.roles = ROLE_TYPE_TAX == roleType ? ROLES_TAX : ROLES_INVOICE;
    }

    /**
     * 获取当前任务所需的角色列表
     *
     * @return 角色列表
     */
    public String[] getRoles() {
        return this.roles;
    }
}
